﻿// -------------------------------------------------------------------------
//    @FileName         :    NFCacheDataLoadTrans.cpp
//    @Author           :    Gao.Yi
//    @Date             :    2025-08-14
//    @Email			:    445267987@qq.com
//    @Module           :    NFCacheDataLoadTrans
//    @Desc             :    缓存数据事务处理类实现
//                           负责单个缓存数据的查询事务，支持批量和单条查询
//                           作为子事务处理存储服务器交互，完成后回调父事务
// -------------------------------------------------------------------------

#include "NFCacheDataLoadTrans.h"

#include "NFCacheDataGetTrans.h"
#include "NFIServerMessageModule.h"

/**
 * @brief 构造函数
 *
 * 根据共享内存管理器��创建模式选择相应的初始化方法：
 * - 冷启动模式：调用 CreateInit() 进行完整初始化
 * - 热启动模式：调用 ResumeInit() 进行恢复初始化
 */
NFCacheDataLoadTrans::NFCacheDataLoadTrans()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode())
    {
        CreateInit();
    }
    else
    {
        ResumeInit();
    }
}

/**
 * @brief 析构函数
 *
 * 清理资源，由于使用共享内存管理，通常无需特殊处理
 */
NFCacheDataLoadTrans::~NFCacheDataLoadTrans()
{
}

/**
 * @brief 冷启动创建时的初始化
 *
 * 对所有成员变量进行零值初始化，确保对象处于干净状态
 *
 * @return 0 表示成功
 */
int NFCacheDataLoadTrans::CreateInit()
{
    m_iReason = 0;           // 查询原因/场景标识
    m_ullRoleId = 0;           // 目标对象ID
    m_iTableId = 0;         // 数据表ID
    m_iTransId = 0;         // 上层批量事务ID
    m_ullTargetId = 0;
    return 0;
}

/**
 * @brief 热启动恢复时的初始化
 *
 * 进程重启后从共享内存恢复对象状态时调用
 * 当前实现为空，如有需要可在此添加恢复逻辑
 *
 * @return 0 表示成功
 */
int NFCacheDataLoadTrans::ResumeInit()
{
    return 0;
}

/**
 * @brief 初始化事务运行参数
 *
 * 设置事务执行所需的基本参数，通常在创建事务后立即调用
 *
 * @param serverType 目标存储服务器类型
 * @param roleId      目标对象ID（单条查询场景使用）
 * @param tableId    数据表ID，用于标识要操作的数据表
 * @param transId    上层批量事务ID，用于回调时定位父事务
 * @return 0 表示成功
 */
int NFCacheDataLoadTrans::Init(int serverType, uint64_t roleId, int tableId, int transId)
{
    m_ullRoleId = roleId;
    m_iServerType = serverType;
    m_iTableId = tableId;
    m_iTransId = transId;
    return 0;
}

/**
 * @brief 处理存储服务器返回的消息
 *
 * 根据命令类型分发处理不同的存储服务器响应消息：
 * - NF_STORESVR_S2C_SELECT：批量查询结果
 * - NF_STORESVR_S2C_SELECTOBJ：单条查询结果
 *
 * @param pSsMsgRes 存储服务器返回的 Protobuf 消息指针
 * @param cmd       消息命令类型
 * @param tableId   数据表ID，用于验证响应是否匹配当前事务
 * @param seq       消息序列号
 * @param errCode   存储服务器返回的错误码
 * @return 0 表示成功处理
 */
int NFCacheDataLoadTrans::HandleDBMsgRes(const google::protobuf::Message* pSsMsgRes, uint32_t cmd, uint32_t tableId, uint32_t seq, int32_t errCode)
{
    int iRetCode = 0;

    // 验证表ID是否匹配当前事务
    if (tableId == (uint32_t)m_iTableId)
    {
        // 根据命令类型分发处理
        if (cmd == NFrame::NF_STORESVR_S2C_SELECT)
        {
            // 处理批量查询结果
            iRetCode = LoadCacheDataBatchRes(dynamic_cast<const NFrame::storesvr_sel_res*>(pSsMsgRes), errCode);
        }
        else if (cmd == NFrame::NF_STORESVR_S2C_SELECTOBJ)
        {
            // 处理单条查询结果
            iRetCode = LoadCacheDataSingleRes(dynamic_cast<const NFrame::storesvr_selobj_res*>(pSsMsgRes), errCode);
        }
        else
        {
            // 未命令类型，记录错误并返回失败
            LOG_ERR(m_ullRoleId, -1, "Unknown command type:{} for tableId:{}", cmd, tableId);
            iRetCode = -1;
        }
    }
    else
    {
        // 表ID不匹配，记录错误
        LOG_ERR(0, -1, "tableId:{} not handle, expected:{}", tableId, m_iTableId);
        iRetCode = -1;
    }

    // 如果处理失败，结束事务
    if (iRetCode != 0)
    {
        SetFinished(iRetCode);
    }

    return 0;
}

/**
 * @brief 事务结束回调处理
 *
 * 当当前事务完成时，通过上层批量事务ID找到父事务并回调结果。
 * 这是事务链式调用的关键环节，确保批量操作能够正确汇总结果。
 *
 * @param iRunLogicRetCode 事务运行逻辑的返回码
 * @return 0 表示回调成功
 */
int NFCacheDataLoadTrans::HandleTransFinished(int iRunLogicRetCode)
{
    if (m_iTransId <= 0) return 0;

    // 根据事务ID获取上层批量事务对象
    NFCacheDataGetTrans* pBatchBase = NFCacheDataGetTrans::GetTrans(m_iTransId);
    CHECK_NULL_WF(m_ullRoleId, pBatchBase, "GetTrans failed, transId:{}", m_iTransId);

    // 回调上层事务的结果处理方法
    int iRetCode = pBatchBase->OnGetCacheDataFinish(m_ullTargetId, m_iTableId, m_iReason, iRunLogicRetCode);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pBatchBase, "{}::LoadCacheDataBatchRes Failed, ullId:{}, tableId:{}, reason:{}", pBatchBase->GetClassName(), m_ullRoleId, m_iTableId, m_iReason);

    return 0;
}

/**
 * @brief 发起批量缓存数据查询请求
 *
 * 虚函数，子类应重写此方法实现具体的批量查询逻辑。
 * 基类实现仅输出警告信息，提醒开发者需要在子类中实现。
 *
 * @param vecId    要查询的ID列表
 * @param enReason 查询原因/场景标识
 * @return 0 表示成功，其他值为错误码
 */
int NFCacheDataLoadTrans::LoadCacheDataBatchReq(const std::vector<uint64_t>& vecId, int enReason)
{
    LOG_WARN(m_ullRoleId, -1, "LoadCacheDataSingleReq not implemented, vecId: {}, enReason: {}", NFCommon::tostr(vecId), enReason);
    return 0;
}

/**
 * @brief 发起单条缓存数据查询请求
 *
 * 虚函数，子类应重写此方法实现具体的单条查询逻辑。
 * 基类实现仅输出警告信息，提醒开发者需要在子类中实现。
 *
 * @param ullId    要查询的目标ID
 * @param enReason 查询原因/场景标识
 * @return 0 表示成功，其他值为错误码
 */
int NFCacheDataLoadTrans::LoadCacheDataSingleReq(uint64_t ullId, int enReason)
{
    // 基类默认实现，输出警告信息
    LOG_WARN(m_ullRoleId, -1, "LoadCacheDataSingleReq not implemented in base class, ullId:{}, enReason:{}", ullId, enReason);
    return 0;
}

/**
 * @brief 单条查询请求（带 Protobuf 数据）
 *
 * 此方法用于发起单条查询请求，并附带一个 Protobuf 数据对象作为额外参数。
 * 子类应重写此方法以实现具体的查询逻辑。
 *
 * @param ullId 查询目标的唯一标识 ID
 * @param enReason 查询原因/场景标识
 * @param stPbClass 附加的 Protobuf 数据对象，包含查询所需的额外信息
 * @return 0 表示成功，其他值为错误码
 *
 * @note 基类实现仅输出警告信息，提醒开发者需要在子类中实现。
 */
int NFCacheDataLoadTrans::LoadCacheDataSingleReq(uint64_t ullId, int enReason, const google::protobuf::Message& stPbClass)
{
    m_ullTargetId = ullId;
    m_iReason = enReason;

    int iRetCode = FindModule<NFIServerMessageModule>()->SendSelectObjTrans((NF_SERVER_TYPE)m_iServerType, ullId, stPbClass, m_iTableId, GetGlobalId());
    CHECK_ERR(m_ullRoleId, iRetCode, "SendSelectObjTrans Failed, ullId:{}", ullId);
    return 0;
}

/**
 * @brief 处理批量查询返回结果
 *
 * 虚函数，子类应重写此方法实现具体的批量查询结果处理逻辑。
 * 基类实现仅输出警告信息，提醒开发者需要在子类中实现。
 *
 * @param pRes    存储服务器返回的批量查询结果
 * @param errCode 错误码
 * @return 0 表示成功，其他值为错误码
 */
int NFCacheDataLoadTrans::LoadCacheDataBatchRes(const NFrame::storesvr_sel_res* pRes, int32_t errCode)
{
    LOG_WARN(m_ullRoleId, -1, "LoadCacheDataBatchRes not implemented, pRes: {}, errCode: {}", pRes ? pRes->DebugString() : "nullptr", errCode);
    return 0;
}

/**
 * @brief 处理单条查询返回结果
 *
 * 虚函数，子类应重写此方法实现具体���单条查询结果处理逻辑。
 * 基类实现仅输出警告信息，提醒开发者需要在子类中实现。
 *
 * @param pRes    存储服务器返回的单条查询结果
 * @param errCode 错误码
 * @return 0 表示成功，其他值为错误码
 */
int NFCacheDataLoadTrans::LoadCacheDataSingleRes(const NFrame::storesvr_selobj_res* pRes, int32_t errCode)
{
    LOG_WARN(m_ullRoleId, -1, "LoadCacheDataSingleRes not implemented, pRes: {}, errCode: {}", pRes ? pRes->DebugString() : "nullptr", errCode);
    return 0;
}
